#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "analyze.h"

void helpNeeded(Option options[],int optionSize, char shortName)
{
    int i;
    printf("\n Aide: \n \n");
    if (shortName=='h') //affiche l'aide de chaque fonction
    {
        for (i=0; i<optionSize; i++) {
            printf("Shortname: -%c \n \t Longname: --%s \n",(options+i)->shortName,(options+i)->longName);
            printf(" \t Parametre attendu:");

            switch((options+i)->parameterType) {
                case PARAM_NONE: printf(" Aucun Parametre \n"); break;
                case PARAM_STRING: printf(" String \n"); break;
                case PARAM_LONG: printf(" Long \n"); break;
                case PARAM_DOUBLE: printf("Double \n"); break;
            };
            
            printf(" \t Description: %s \n \t Description du Parametre: %s \n \n",(options+i)->description,(options+i)->parameterDescription);
        }
    }
    else {
        // Parcours le tableau jusqu'a trouver shortName et affiche l'aide correspondante
        i=0;
        while ( ((options+i)->shortName)!=shortName && (i<optionSize) )
        {
            i++;
        }
        printf("Shortname: -%c \n\tLongname: --%s",(options+i)->shortName,(options+i)->longName);
        printf("\n \tParametre: ");
            switch((options+i)->parameterType) {
                case PARAM_NONE: printf("Aucun Parametre \n"); break;
                case PARAM_STRING: printf("String \n"); break;
                case PARAM_LONG: printf("Long \n"); break;
                case PARAM_DOUBLE: printf("Double \n"); break;
            };

            printf("\tDescription: %s \n\tDescription du Parametre: %s\n",(options+i)->description,(options+i)->parameterDescription);

    }
    exit(EXIT_FAILURE);
}
int longargv(Option options[], int optionSize, char **argv, int i, int argc)
{
    int j;
    int *intp=NULL;
    long *longp=NULL;
    double *doublep=NULL;
    char *chaine=NULL;
    Option *currentOption=NULL;

    if (strcasecmp(argv[i]+2, "help")==0)
    {
        helpNeeded(options, optionSize, 'h');
    }
    else
    {
            for (j = 0; j < optionSize; j++) //recherche de l'options
            {
                if (strcasecmp(argv[i] + 2, (options+j)->longName) == 0) // argv[i]+2 décale de 2 caractère sur la droite la comparaison de la chaine
                {
                    currentOption=options+j;
                    break;
                }
            }
            if (currentOption!=NULL) //option présente ou non
            {
                switch (currentOption->parameterType) {
                    case PARAM_NONE:
                        if ( (i==(argc-1)))
                        {
                            intp = (int*) malloc(sizeof (int));
                            *intp = 1;
                            currentOption->parameterPtr = (void*) intp;
                            i++;
                            break;
                        }
                        else
                        {
                            if (i<argc-1)
                            {
                                if ((strncmp(argv[i + 1], "-", 1) == 0) || (strncmp(argv[i + 1], "--", 2) == 0))
                                {
                                    intp = (int*) malloc(sizeof (int));
                                    *intp = 1;
                                    currentOption->parameterPtr = (void*) intp;
                                    i++;
                                    break;
                                }
                                else
                                {
                                    printf("Attention l'argument %s n'a pas besoin de parametre", argv[i]);
                                    helpNeeded(options, optionSize, currentOption->shortName);
                                }
                            }
                        }

                        case PARAM_STRING:
                            if ( i==(argc-1))
                            {
                                printf("Attention il manque un argument");
                                helpNeeded(options,optionSize, currentOption->shortName);
                            }
                            else
                            {
                                if ((strncmp(argv[i+1], "-", 1) != 0) && (strncmp(argv[i+1], "--", 2) != 0))
                                {
                                    chaine = (char*) malloc(sizeof (char) *(strlen(argv[i + 1]) + 1));
                                    strcpy(chaine, argv[i+1]);
                                    currentOption->parameterPtr = (void*) chaine;
                                    i = i + 2;
                                    break;
                                }
                                else
                                {
                                    printf("Attention l'argument %s n'a pas de parametre",argv[i]);
                                    helpNeeded(options, optionSize, currentOption->shortName);
                                }
                            }
                        case PARAM_LONG:
                            if ( i==(argc-1))
                            {
                                printf("Attention il manque un argument");
                                helpNeeded(options,optionSize, currentOption->shortName);
                            }
                            else
                            {
                                longp = (long*) malloc(sizeof (long));
                                if (sscanf(argv[i+1],"%ld",longp)==1)
                                {
                                    currentOption->parameterPtr = (void*) longp;
                                    i = i + 2;
                                    break;
                                }
                                else
                                {
                                    printf("Attention mauvais parametre de %s",argv[i]);
                                    free(longp);
                                    helpNeeded(options, optionSize, currentOption->shortName);
                                }
                            }
                            
                        case PARAM_DOUBLE:
                            if ( i==(argc-1))
                            {
                                printf("Attention il manque un argument");
                                helpNeeded(options,optionSize, currentOption->shortName);
                            }
                            else
                            {
                                doublep = (double*) malloc(sizeof (double));
                                if (sscanf(argv[i+1],"%lf",doublep)==1)
                                {
                                    currentOption->parameterPtr = (void*) longp;
                                    i = i + 2;
                                    break;
                                }
                                else
                                {
                                    printf("Attention mauvais parametre de %s",argv[i]);
                                    free(doublep);
                                    helpNeeded(options, optionSize, currentOption->shortName);
                                }
                            }

                        default:
                            printf("Erreur: \n");
                            helpNeeded(options, optionSize, 'h');
                            break;
                    }
            }
            else
            {
                printf("Option Invalide\n");
                helpNeeded(options,optionSize, 'h');
            }
        }
    return i;
}

int shortargv(Option options[], int optionSize, char **argv, int i, int argc)
{
    int j,k,l;
    int *intp=NULL;
    long *longp=NULL;
    double *doublep=NULL;
    char *chaine=NULL;
    Option *currentOption=NULL;

    j=1;
    l=0;

    if (strncasecmp(argv[i]+1, "h", 1) == 0)
    {
        helpNeeded(options, optionSize, 'h');
    }
    else
    {
        if (strlen(argv[i]) > strlen("-h"))
        {
            while (j<(strlen(argv[i])))
            {
                for (k = 0; k < optionSize; k++) //recherche de l'options
                {
                    if (strncasecmp(argv[i]+j, &(options + k)->shortName, 1) == 0)
                    {
                        currentOption = options + k;
                        break;
                    }
                }
                if (currentOption != NULL)
                {
                    switch (currentOption->parameterType)
                    {
                        case PARAM_NONE:
                            intp = (int*) malloc(sizeof (int));
                            *intp = 1;
                            currentOption->parameterPtr = (void*) intp;
                            j++;
                            break;
                        case PARAM_STRING:
                            if (i+l+1== argc) //dernier ?
                            {
                                printf("Attention ! Il manque un argument \n");
                                helpNeeded(options, optionSize, currentOption->shortName);
                            } 
                            else
                            {
                                if ((strncmp(argv[i+l+1], "-", 1) != 0) && (strncmp(argv[i+l+1], "--", 2) != 0))
                                {
                                    chaine = (char*) malloc(sizeof (char) *(strlen(argv[i+l+1])+1));
                                    strcpy(chaine, argv[i+l+1]);
                                    currentOption->parameterPtr = (void*) chaine;
                                    l++;
                                    j++;
                                    break;
                                } 
                                else
                                {
                                    printf("Attention l'argument %s n'a pas de parametre", argv[i] + j);
                                    helpNeeded(options, optionSize, currentOption->shortName);
                                }
                            }
                        case PARAM_LONG:
                            longp = (long*) malloc(sizeof (long));
                            if (sscanf(argv[i+l+1], "%ld", longp) == 1)
                            {
                                currentOption->parameterPtr = (void*) longp;
                                l++;
                                j++;
                                break;
                            } 
                            else
                            {
                                printf("Attention mauvais parametre de %s", argv[i]);
                                free(longp);
                                helpNeeded(options, optionSize, currentOption->shortName);
                            }
                        case PARAM_DOUBLE:
                            doublep = (double*) malloc(sizeof (double));
                            if (sscanf(argv[i+l+1], "%lf", doublep) == 1)
                            {
                                currentOption->parameterPtr = (void*) longp;
                                l++;
                                j++;
                                break;
                            } 
                            else
                            {
                                printf("Attention mauvais parametre de %s", argv[i]);
                                free(doublep);
                                helpNeeded(options, optionSize, currentOption->shortName);
                            }
                        default:
                            printf("Erreur: \n");
                            helpNeeded(options, optionSize, 'h');
                            break;
                    }
                }
            }
            i=i+l;
        } 
        else
        {
            for (j = 0; j < optionSize; j++) //recherche de l'options
            {
                if (strncasecmp(argv[i] + 1, &(options + j)->shortName, 1) == 0)
                {
                    currentOption = options + j;
                    break;
                }
            }
            if (currentOption != NULL) //option présente ou non
            {
                switch (currentOption->parameterType)
                {
                    case PARAM_NONE:
                        intp = (int*) malloc(sizeof (int));
                        *intp = 1;
                        currentOption->parameterPtr = (void*) intp;
                        j++;
                        break;

                    case PARAM_STRING:
                        if (i + 1 == argc) //test si fin d'argument
                        {
                            printf("Attention il manque un argument");
                            helpNeeded(options, optionSize, 'h');
                        }
                        else
                        {
                            if ((strncmp(argv[i + 1], "-", 1) != 0) && (strncmp(argv[i + 1], "--", 2) != 0))
                            {
                                chaine = (char*) malloc(sizeof (char) *(strlen(argv[i + 1]) + 1));
                                strcpy(chaine, argv[i + 1]);
                                currentOption->parameterPtr = (void*) chaine;
                                i = i + 2;
                                break;
                            }
                            else
                            {
                                printf("Attention l'argument %s n'a pas de parametre", argv[i]);
                                helpNeeded(options, optionSize, currentOption->shortName);
                            }
                        }

                    case PARAM_LONG:
                        if (i + 1 == argc) //test si fin d'argument
                        {
                            printf("Attention il manque un argument");
                            helpNeeded(options, optionSize, 'h');
                        }
                        else
                        {
                            longp = (long*) malloc(sizeof (long));
                            if (sscanf(argv[i + 1], "%ld", longp) == 1) {
                                currentOption->parameterPtr = (void*) longp;
                                i = i + 2;
                                break;
                            }
                            else
                            {
                                printf("Attention mauvais parametre de %s", argv[i]);
                                free(longp);
                                helpNeeded(options, optionSize, currentOption->shortName);
                            }
                        }


                    case PARAM_DOUBLE:
                        if (i+1==argc) //test si fin d'argument
                        {
                            printf("Attention il manque un argument");
                            helpNeeded(options, optionSize, 'h');
                        }
                        else
                        {
                            doublep = (double*) malloc(sizeof (double));
                            if (sscanf(argv[i + 1], "%lf", doublep) == 1)
                            {
                                currentOption->parameterPtr = (void*) doublep;
                                i = i + 2;
                                break;
                            }
                            else
                            {
                                printf("Attention mauvais parametre de %s", argv[i]);
                                free(doublep);
                                helpNeeded(options, optionSize, currentOption->shortName);
                            }
                        }
                    default:
                        printf("Erreur: \n");
                        helpNeeded(options, optionSize, 'h');
                        break;
                }
            }
            else
            {
                printf("Option Invalide\n");
                helpNeeded(options, optionSize, 'h');
            }
        }
    }
    return i;
}

void analyzeCommandLineArguments(Option options[], int optionSize, int argc, char **argv)
{
    int i;

    for (i = 0; i < optionSize; i++) //initilaisation des pointeur sur parametre à une adresse NULL
        {
            (options+i)->parameterPtr = NULL;
        }

    if ( argc==1 )
    {
        printf("Besoin de plus d'arguments \n");
        helpNeeded(options, optionSize,'h');
    }
    else
    {   
        i = 1;
        while (i < argc && strncmp(argv[i],"-",1)==0)
        {
            if (strncmp(argv[i], "--", 2) == 0) //Test appel du nom long
            {
                i=longargv(options, optionSize, argv, i, argc); //Fct retourne i incrémenté suivant le cas
            }
            else
            {
                i=shortargv(options, optionSize, argv,i,argc);
            }
        }
    }
}